package com.cloudkinto.service.order.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.DicBusinessItemConstant;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.*;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.operate.OperateRecordService;
import com.cloudkinto.service.operate.vo.OperateRes;
import com.cloudkinto.service.order.OrderAmazonService;
import com.cloudkinto.service.order.vo.FeedUploadResultBean;
import com.cloudkinto.service.order.vo.ListOrdersResultEntitySP;
import com.cloudkinto.service.order.vo.OrdersEntitySP;
import com.cloudkinto.service.order.vo.amazon.*;
import com.cloudkinto.service.order.vo.amazon.amazonorder.ListOrdersResult;
import com.cloudkinto.service.order.vo.amazon.amazonorder.OrderFulfillment;
import com.cloudkinto.service.order.vo.amazon.amazonorder.OrderItemsResponse;
import com.cloudkinto.service.order.vo.amazon.amazonorder.OrderItemsSPEntity;
import com.cloudkinto.service.orderoutput.OrderOutputService;
import com.cloudkinto.service.orderoutput.vo.OrderOutputAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputPackageAddReq;
import com.cloudkinto.service.orderoutput.vo.OrderOutputPackageDetail;
import com.cloudkinto.service.orderoutput.vo.OrderOutputProductAddReq;
import com.cloudkinto.service.region.JpRegionService;
import com.cloudkinto.service.shipprice.ShipPriceService;
import com.cloudkinto.service.shop.ShopService;
import com.cloudkinto.utils.amazon.AmazonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author 张永远
 * @since 2020-06-02
 */
@Service
@Slf4j
public class OrderAmazonServiceImpl extends ServiceImpl<OrderAmazonDao, OrderAmazonDo> implements OrderAmazonService {

    @Autowired
    private OrderAmazonDao dao;
    @Autowired
    private OrderAmazonItemsDao orderAmazonItemsDao;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private OrderOutputDao orderOutputDao;
    @Autowired
    private OrderOutputPackageDao orderOutputPackageDao;
    @Autowired
    private OrderOutputPackageDetailDao orderOutputPackageDetailDao;
    @Autowired
    private ProductSkuMapDao productSkuMapDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private ShopService shopService;
    @Autowired
    private OperateRecordService operateRecordDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private OrderOutputService orderOutputService;
    @Autowired
    private JpRegionService mRegionService;
    @Autowired
    private StockRecordDao stockDao;
    @Autowired
    private ShipPriceService shipPriceService;
    @Autowired
    private StorageDao storageDao;
    @Autowired
    private RedisTemplate redisTemplate;
    private String AMZACCESSTOKEN = "AMZACCESSTOKEN:";
    private String AMZACCESRDTSTOKEN = "AMZACCESSRDTTOKEN:";
    private String STSSESSIONTOKEN = "STSSESSIONSTOKEN";
    private OrderAmazonDao orderAmazonDoPiiDao;

    @Override
    public SingleResult addInit(Long userId, Long companyId) {
        return SingleResult.success(shopService.selectShopListInit(userId, companyId));
    }

    @Override
    @Async
    public SingleResult downloadAmazonOrdersSP(AmazonOrderDownReq req) throws Exception {
        ShopDo shopDo = shopDao.selectById(req.getShopId());
        if (shopDo == null || StringUtils.isBlank(shopDo.getAmazonSellerId())) {
            throw new BizException(SysConstant.Shop_Token_Error);
        }
        Map params = new HashMap();
        String after = "";
        String before = "";
        String nextToken = "";
        if (req.getBeforeDate() != null) {
            after = new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(req.getBeforeDate().getTime() - 8 * 60 * 60 * 1000);
            params.put("LastUpdatedAfter", after);
        }
        if (req.getAfterDate() != null && req.getAfterDate().getTime() < new Date(System.currentTimeMillis() - 2 * 60 * 1000).getTime()) {
            before = new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(req.getAfterDate().getTime() - 8 * 60 * 60 * 1000);
            params.put("LastUpdatedBefore", before);
        }
        if (req.getUserId() != null) {
            params.put("FulfillmentChannels", "MFN");
        }
        String lwa = shopDo.getAmzSpLwa();
        String accessToken = getAccessToken(shopDo);
        params.put("MarketplaceIds", "A1VC38T7YXB528");
        for (int i = 0; i < 100; i++) {
            if (StringUtils.isNotBlank(nextToken)) {
                params.put("NextToken", nextToken);
            }
            String result = AmazonUtil.spOrderList(GlobalConstants.AmazonSPAPIURL + "/orders/v0/orders/", accessToken, getAwsSTSSessionToken(), params);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {
                if (jsonObject.getJSONArray("errors").getJSONObject(0).getString("code").equals("Unauthorized")) {
                    accessToken = getAccessToken(shopDo);
                    result = AmazonUtil.spOrderList(GlobalConstants.AmazonSPAPIURL + "/orders/v0/orders/", accessToken, getAwsSTSSessionToken(), params);
                    jsonObject = JSON.parseObject(result);
                } else {
                    log.error("亚马逊订单同步错误" + jsonObject.getJSONArray("errors").toJSONString());
                    return SingleResult.failure(jsonObject.getJSONArray("errors").getJSONObject(0).toJSONString());
                }
            }
            try {
                //主表对象
                ListOrdersResultEntitySP orderReponse = JSONObject.parseObject(jsonObject.get("payload").toString(), ListOrdersResultEntitySP.class);
                nextToken = orderReponse.getNextToken();
                dealWithSPOrderAddressAndItems(orderReponse, shopDo, accessToken);
                while (StringUtils.isBlank(nextToken)) {
                    return SingleResult.success();
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
                return SingleResult.failure("刷新频率太快，请稍等5分钟再操作");
            }
        }
        return SingleResult.success();
    }

    private String getAccessToken(ShopDo shopDo) throws Exception {
        String accessToken = (String) redisTemplate.opsForValue().get(AMZACCESSTOKEN + shopDo.getId());
        if (accessToken != null) {
            return accessToken;
        }
        String sessionTokenData = getAwsSTSSessionToken();
        accessToken = AmazonUtil.spGetToken(GlobalConstants.AmzSpClientId, GlobalConstants.AmzSpClientSecret, shopDo.getAmzSpLwa(), sessionTokenData);
        redisTemplate.opsForValue().set(AMZACCESSTOKEN + shopDo.getId(), accessToken, 3300, TimeUnit.SECONDS);
        return accessToken;
    }

    private String getAwsSTSSessionToken() {
        JSONObject jsonObject;
        jsonObject = (JSONObject) redisTemplate.opsForValue().get(STSSESSIONTOKEN);
        if (jsonObject != null) {
            GlobalConstants.accessSecrityKeySP = jsonObject.getString("AccessKeyId");
            GlobalConstants.secretSecrityKeySP = jsonObject.getString("SecretAccessKey");
            return jsonObject.getString("SessionToken");
        }
        Map parametersMap = new HashMap<>();
        parametersMap.put("Action", "AssumeRole");
        parametersMap.put("Version", "2011-06-15");
        parametersMap.put("RoleArn", "arn:aws:iam::975458911230:role/FBA-SP-API");
        parametersMap.put("RoleSessionName", "dingSession");
        String body = null;
        try {
            body = AmazonUtil.awsSTS("https://sts.us-west-2.amazonaws.com/", parametersMap);
            jsonObject = XmlUtils.xml2Json(body);
            JSONObject resultData = jsonObject.getJSONObject("AssumeRoleResponse").getJSONArray("AssumeRoleResult").getJSONObject(0).getJSONArray("Credentials").getJSONObject(0);
            redisTemplate.opsForValue().set(STSSESSIONTOKEN, resultData, 3600, TimeUnit.SECONDS);
            GlobalConstants.accessSecrityKeySP = resultData.getString("AccessKeyId");
            GlobalConstants.secretSecrityKeySP = resultData.getString("SecretAccessKey");
            String sessionToken = resultData.getString("SessionToken");
            return sessionToken;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private void dealWithSPOrderAddressAndItems(ListOrdersResultEntitySP orderReponse, ShopDo shopDo, String accessToken) {
        if (!CollectionUtils.isEmpty(orderReponse.getOrders())) {
            for (OrdersEntitySP orderEntity : orderReponse.getOrders()) {
                //附表对象
                OrderItemsSPEntity itemsResponse = null;
                OrdersEntitySP.ShippingAddressEntity shippingAddressEntity = null;
                QueryWrapper<OrderAmazonDo> wrapper = new QueryWrapper<>();
                wrapper.eq("amazon_order_number", orderEntity.getAmazonOrderId());
                List<OrderAmazonDo> orderAmazonDos = dao.selectList(wrapper);
                OrderAmazonDo orderAmazonDo = null;
                if (orderAmazonDos.size() == 1) {
                    orderAmazonDo = orderAmazonDos.get(orderAmazonDos.size() - 1);
                } else if (orderAmazonDos.size() > 1) {
                    for (int i = 0; i < orderAmazonDos.size(); i++) {
                        if (i == orderAmazonDos.size() - 1) {
                            orderAmazonDo = orderAmazonDos.get(orderAmazonDos.size() - 1);
                        } else {
                            dao.deleteById(orderAmazonDos.get(0).getId());
                        }
                    }
                }
                if (orderAmazonDo == null || orderAmazonDo.getCommoditySku() == null || orderAmazonDo.getShipAddress() == null ||
                        TimeUtils.getDateTime2(orderEntity.getLastUpdateDate()).getTime() - orderAmazonDo.getLastUpdateDate().getTime() > 1000) {
                    try {
                        Thread.sleep(1500);
                        Map<String, String> parametersMap = new HashMap<>();
                        parametersMap.put("orderId", orderEntity.getAmazonOrderId());
                        String resultOrderAddress = "";
                        if (orderEntity.getFulfillmentChannel().equals("MFN")) {
                            if (orderEntity.getOrderStatus().equals("Unshipped") ||
                                    orderEntity.getOrderStatus().equals("PendingAvailability") ||
                                    orderEntity.getOrderStatus().equals("Shipped")) {
                                resultOrderAddress = AmazonUtil.spOrder(GlobalConstants.AmazonSPAPIURL + "/orders/v0/orders/" + orderEntity.getAmazonOrderId() + "/address", accessToken, getAwsSTSSessionToken(), parametersMap);
                                if (StringUtils.isNotBlank(resultOrderAddress)) {
                                    JSONObject jsonObjectAddress = JSON.parseObject(resultOrderAddress);
                                    String addressInfo = jsonObjectAddress.getJSONObject("payload").getJSONObject("ShippingAddress").toString();
                                    shippingAddressEntity = JSON.parseObject(addressInfo, OrdersEntitySP.ShippingAddressEntity.class);
                                }
                            }
                        }
                        String resulttOrderItems = AmazonUtil.spOrder(GlobalConstants.AmazonSPAPIURL + "/orders/v0/orders/" + orderEntity.getAmazonOrderId() + "/orderItems", accessToken, getAwsSTSSessionToken(), parametersMap);

                        JSONObject itemJsonResult = JSON.parseObject(resulttOrderItems);
                        if (itemJsonResult != null) {
                            itemsResponse = JSON.parseObject(itemJsonResult.getJSONObject("payload").toString(), OrderItemsSPEntity.class);
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                    handlerOderSPInsert(shopDo, orderAmazonDo, shippingAddressEntity, orderEntity, itemsResponse);
                }
            }
        }
    }

    private void handlerOderSPInsert(ShopDo shopDo, OrderAmazonDo orderAmazonDo, OrdersEntitySP.ShippingAddressEntity shippingAddressEntity, OrdersEntitySP orderEntity, OrderItemsSPEntity itemsResponse) {
        if (orderAmazonDo == null)
            orderAmazonDo = new OrderAmazonDo();
        orderAmazonDo.setAmazonOrderNumber(orderEntity.getAmazonOrderId());
        orderAmazonDo.setPurchaseDate(TimeUtils.getDateTime2(orderEntity.getPurchaseDate()));  //2020-05-02T14:59:59Z
        orderAmazonDo.setLastUpdateDate(TimeUtils.getDateTime2(orderEntity.getLastUpdateDate()));  //2020-05-02T14:59:59Z
        orderAmazonDo.setOrderStatus(orderEntity.getOrderStatus());
        orderAmazonDo.setFulfillmentChannel(orderEntity.getFulfillmentChannel());
        orderAmazonDo.setSalesChannel(orderEntity.getSalesChannel());
        orderAmazonDo.setShipServiceLevel(orderEntity.getShipServiceLevel());
        if (shippingAddressEntity != null) {
            try {
                orderAmazonDo.setShipAddress(getStr(shippingAddressEntity.getAddressLine1()) +
                        getStr(shippingAddressEntity.getAddressLine2()) + getStr(shippingAddressEntity.getAddressLine3()));
                orderAmazonDo.setShipName(shippingAddressEntity.getName());
                orderAmazonDo.setShipCity(shippingAddressEntity.getCity());
                orderAmazonDo.setShipCounty(shippingAddressEntity.getCounty());
                orderAmazonDo.setShipDistrict(shippingAddressEntity.getDistrict());
                orderAmazonDo.setShipStateOrRegion(shippingAddressEntity.getStateOrRegion());
                orderAmazonDo.setPostalCode(shippingAddressEntity.getPostalCode()); //ship
                orderAmazonDo.setShipPhone(shippingAddressEntity.getPhone());
                orderAmazonDo.setShipAddressType(shippingAddressEntity.getAddressType());
            } catch (Exception e) {
                log.error("Amazon地址转换错误" + e.getMessage());
            }
        }
        orderAmazonDo.setSellerOrderNumber(orderEntity.getSellerOrderId());
//        orderAmazonDo.setOrderChannel(orderEntity.getOrderChannel());

        if (orderEntity.getOrderTotal() != null) {
            orderAmazonDo.setOrderTotal(orderEntity.getOrderTotal().getAmount()); //OrderTotalEntity
        }

        orderAmazonDo.setShipmentServiceLevelCategory(orderEntity.getShipmentServiceLevelCategory());
        orderAmazonDo.setPaymentMethod(orderEntity.getPaymentMethod());
        if ("COD".equals(orderEntity.getPaymentMethod()) && orderEntity.getPaymentExecutionDetail() != null) {
            if (orderEntity.getPaymentExecutionDetail().size() > 0) {
                double sum = orderEntity.getPaymentExecutionDetail().stream().mapToDouble(paymentMethodDetailsEntity -> {
                    if (paymentMethodDetailsEntity.getPayment() != null &&
                            StringUtils.isNotBlank(paymentMethodDetailsEntity.getPayment().getAmount())) {
                        return Double.parseDouble(paymentMethodDetailsEntity.getPayment().getAmount());
                    } else {
                        return 0;
                    }
                }).sum();
                orderAmazonDo.setPaymentCod(String.valueOf(sum));
            }
        }
        //todo buyer信息
//        orderAmazonDo.setBuyerEmail(orderEntity.getBuyerEmail());
//        orderAmazonDo.setBuyerName(orderEntity.getBuyerName());
        orderAmazonDo.setOrderType(orderEntity.getOrderType());
        orderAmazonDo.setEarliestShipDate(TimeUtils.getDateTime2(orderEntity.getEarliestShipDate()));
        orderAmazonDo.setLastShipDate(TimeUtils.getDateTime2(orderEntity.getLatestShipDate()));
        orderAmazonDo.setEarliestDeliveryDate(TimeUtils.getDateTime2(orderEntity.getEarliestDeliveryDate()));
        orderAmazonDo.setLastDeliveryDate(TimeUtils.getDateTime2(orderEntity.getLatestDeliveryDate()));
        orderAmazonDo.setShopId(shopDo.getId());
        orderAmazonDo.setCompanyId(shopDo.getCompanyId());
        StringBuilder sb = new StringBuilder();
        if (itemsResponse != null) {
            for (OrderItemsSPEntity.OrderItemsEntity itemEntity : itemsResponse.getOrderItems()) {
                if (sb.length() > 1) {
                    sb.append(",");
                }
                if (shopDo.getId() == 1) {
                    sb.append(itemEntity.getSellerSKU().replaceAll("BFBA-", "").replaceAll("FBA-", ""));
                } else {
                    sb.append(itemEntity.getSellerSKU());
                }
            }
            orderAmazonDo.setCommoditySku(sb.toString());
        }

        if (orderAmazonDo.getId() == null || orderAmazonDo.getId() == 0) {
            dao.insert(orderAmazonDo);
        } else {
            dao.updateById(orderAmazonDo);
        }
        if (itemsResponse == null) {
            return;
        }

        for (OrderItemsSPEntity.OrderItemsEntity itemOrderEntity :
                itemsResponse.getOrderItems()) {
            OrderAmazonItemsDo itemsDo = new OrderAmazonItemsDo();
            itemsDo.setOrderAmazonId(orderAmazonDo.getId());
            itemsDo.setAsin(itemOrderEntity.getASIN());
            if (shopDo.getId() == 1) {
                itemsDo.setSellerSku(itemOrderEntity.getSellerSKU().replaceAll("BFBA-", "").replaceAll("FBA-", ""));
            } else {
                itemsDo.setSellerSku(itemOrderEntity.getSellerSKU());
            }
            Long productId = getProductId(itemsDo.getSellerSku(), shopDo.getCompanyId());
            itemsDo.setSystemSku(productId);
            itemsDo.setTitle(itemOrderEntity.getTitle());
            try {
                itemsDo.setQuantityOrdered((itemOrderEntity.getQuantityOrdered()));
                itemsDo.setQuantityShipped((itemOrderEntity.getQuantityShipped()));
            } catch (Exception e) {
                log.error(e.getMessage());
            }
            if (itemOrderEntity.getItemPrice() != null) {
                itemsDo.setItemPrice(itemOrderEntity.getItemPrice().getAmount());
            }
            if (itemOrderEntity.getCoDFee() != null) {
                itemsDo.setCodFee(itemOrderEntity.getCoDFee().getAmount());
            }
            itemsDo.setItemId(itemOrderEntity.getOrderItemId());
            itemsDo.setIsGift(StringUtils.isNotBlank(itemOrderEntity.getIsGift()) && "true".equals(itemOrderEntity.getIsGift()) ? 1 : 0);
            QueryWrapper wrapper1 = new QueryWrapper();
            wrapper1.eq("item_id", itemsDo.getItemId());
            OrderAmazonItemsDo amazonItemsDo = orderAmazonItemsDao.selectOne(wrapper1);
            if (amazonItemsDo == null) {
                orderAmazonItemsDao.insert(itemsDo);
            } else {
                itemsDo.setId(amazonItemsDo.getId());
                orderAmazonItemsDao.updateById(itemsDo);
            }
        }
    }

    @Override
    public SingleResult selectAmazonOrderApi(AmazonOrderDownReq req, Long userId, Long companyId) throws Exception {
        ShopDo shopDo = shopDao.selectById(req.getShopId());
        req.setUserId(userId);
        if (shopDo == null) {
            throw new BizException(SysConstant.Shop_NotExist);
        } else if (shopDo.getAmzSpLwa() != null) {
            return downloadAmazonOrdersSP(req);
        } else if (shopDo.getAmazonSellerId() != null && shopDo.getAmazonToken() != null) {
            return downloadAmazonOrders(req, userId, companyId);
        } else {
            throw new BizException(SysConstant.Shop_Token_Error);
        }
    }

    @Override
    @Async
    public SingleResult downloadAmazonOrders(AmazonOrderDownReq req, Long userId, Long companyId) throws Exception {
        if (companyId == null) {
            throw new BizException(SysConstant.Error_Company);
        }
        ShopDo shopDo = shopDao.selectById(req.getShopId());
        if (shopDo == null || StringUtils.isBlank(shopDo.getAmazonSellerId())) {
            throw new BizException(SysConstant.Shop_Token_Error);
        }

        String now = new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(new Date(System.currentTimeMillis() - 8 * 60 * 60 * 1000));
        String after = "";
        String before = "";
        if (req.getBeforeDate() != null) {
            after = new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(req.getBeforeDate().getTime() - 9 * 60 * 60 * 1000);
        }
        if (req.getAfterDate() != null && req.getAfterDate().getTime() < new Date(System.currentTimeMillis() + 58 * 60 * 1000).getTime()) {

            before = new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(req.getAfterDate().getTime() - 9 * 60 * 60 * 1000);
        }

        Map params = new HashMap();
        params.put("MWSAuthToken", shopDo.getAmazonToken());
        params.put("SellerId", shopDo.getAmazonSellerId());
        if (userId != 0) {
            params.put("FulfillmentChannel.Channel.1", "MFN");
        }
        String amazonSecret = GlobalConstants.amazonSecret;
        if (shopDo.getId() == 1) {
            params.put("AWSAccessKeyId", GlobalConstants.accessKey);
            params.put("MarketplaceId.Id.1", GlobalConstants.marketplaceId);
            amazonSecret = GlobalConstants.secretKey;
        } else if (shopDo.getId() == 19) {
            params.put("AWSAccessKeyId", GlobalConstants.accessKey1014);
            params.put("MarketplaceId.Id.1", GlobalConstants.marketplaceId);
            amazonSecret = GlobalConstants.secretKey1014;
        } else {
            params.put("AWSAccessKeyId", GlobalConstants.amazonAccessKey);
            params.put("MarketplaceId.Id.1", GlobalConstants.marketplaceId);
        }
        Map itemMap = new HashMap(params);

        String result = AmazonUtil.doPostOrderList(now, before, after, GlobalConstants.AmazonURL + "/Orders/2013-09-01", params, amazonSecret, "");

        try {
            JSONObject jsonResult = JSON.parseObject(result, JSONObject.class);
            //主表对象
            ListOrdersResult ordersResult = JSON.parseObject(jsonResult.getJSONObject("ListOrdersResponse").toJSONString(), ListOrdersResult.class);

            List<ListOrdersResult.ListOrdersResultEntity.OrdersEntity.OrderEntity> orderList = ordersResult.getListOrdersResult().get(0).getOrders().get(0).getOrder();

            dealWithOrderANdItems(new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(new Date(System.currentTimeMillis() - 8 * 60 * 60 * 1000)), companyId, orderList, req, params, amazonSecret);
            if (StringUtils.isNotBlank(ordersResult.getListOrdersResult().get(0).getNextToken())) {
                now = new SimpleDateFormat(GlobalConstants.TIME_FORMAT_STR).format(new Date(System.currentTimeMillis() - 8 * 60 * 60 * 1000));
                result = AmazonUtil.doPostOrderListByToken(now, ordersResult.getListOrdersResult().get(0).getNextToken(),
                        GlobalConstants.AmazonURL + "/Orders/2013-09-01", params, amazonSecret, "");
                //主表对象
                jsonResult = JSON.parseObject(result, JSONObject.class);
                ordersResult = JSON.parseObject(jsonResult.getJSONObject("ListOrdersByNextTokenResponse").toJSONString(), ListOrdersResult.class);

                orderList = ordersResult.getListOrdersByNextTokenResult().get(0).getOrders().get(0).getOrder();

                dealWithOrderANdItems(now, companyId, orderList, req, params, amazonSecret);
                while (StringUtils.isNotBlank(ordersResult.getListOrdersByNextTokenResult().get(0).getNextToken())) {
                    result = AmazonUtil.doPostOrderListByToken(now, ordersResult.getListOrdersByNextTokenResult().get(0).getNextToken(),
                            GlobalConstants.AmazonURL + "/Orders/2013-09-01", params, amazonSecret, "");
                    //主表对象
                    jsonResult = JSON.parseObject(result, JSONObject.class);
                    ordersResult = JSON.parseObject(jsonResult.getJSONObject("ListOrdersByNextTokenResponse").toJSONString(), ListOrdersResult.class);

                    orderList = ordersResult.getListOrdersByNextTokenResult().get(0).getOrders().get(0).getOrder();

                    dealWithOrderANdItems(now, companyId, orderList, req, params, amazonSecret);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return SingleResult.failure("刷新频率太快，请稍等5分钟再操作");
        }

        return SingleResult.success();
    }

    private void dealWithOrderANdItems(String now, Long companyId, List<ListOrdersResult.ListOrdersResultEntity.OrdersEntity.OrderEntity> orderList,
                                       AmazonOrderDownReq req, Map params, String amazonSecret) throws Exception {
        if (!CollectionUtils.isEmpty(orderList)) {
            for (ListOrdersResult.ListOrdersResultEntity.OrdersEntity.OrderEntity orderEntity : orderList) {
                //附表对象
                OrderItemsResponse itemsResponse = null;
                QueryWrapper<OrderAmazonDo> wrapper = new QueryWrapper<>();
                wrapper.eq("amazon_order_number", orderEntity.getAmazonOrderId());
                OrderAmazonDo orderAmazonDo = dao.selectOne(wrapper);
                //判断订单更新时间有没有变化
                if (orderAmazonDo == null || orderAmazonDo.getCommoditySku() == null
                        || TimeUtils.getDateTime(orderEntity.getLastUpdateDate()).getTime() - orderAmazonDo.getLastUpdateDate().getTime() > 1000) {
//                    if ("Unshipped".equals(orderEntity.getOrderStatus())
//                            || "Shipped".equals(orderEntity.getOrderStatus())
//                            || "PartiallyShipped".equals(orderEntity.getOrderStatus())) {
                    Thread.sleep(2000);
                    params.put("AmazonOrderId", orderEntity.getAmazonOrderId());
                    if (params.containsKey("Signature")) {
                        params.remove("Signature");
                    }
                    if (params.containsKey("LastUpdatedAfter")) {
                        params.remove("LastUpdatedAfter");
                    }
                    if (params.containsKey("LastUpdatedBefore")) {
                        params.remove("LastUpdatedBefore");
                    }
                    String resultItem = AmazonUtil.doPostSubmitFeedItem(now, GlobalConstants.AmazonURL + "/Orders/2013-09-01", params, amazonSecret);
                    JSONObject itemJsonResult = JSON.parseObject(resultItem, JSONObject.class);
                    try {
                        itemsResponse = JSON.parseObject(itemJsonResult.getJSONObject("ListOrderItemsResponse").toJSONString(), OrderItemsResponse.class);
                    } catch (Exception e) {
                        log.error(resultItem);
                        if (resultItem.contains("Error") && resultItem.contains("Throttled")) {
                            break;
                        }
                    }
                    handlerOderInsert(req.getShopId(), companyId, orderAmazonDo, orderEntity, itemsResponse);
                }
            }
        }
    }

    @Override
    public void exportExcel(Map<String, String> map, List<Long> ids, HttpServletResponse response) throws
            IOException {
        List<OrderAmazonDo> orderAmazonDoList = new ArrayList<>();
        if (ids == null || ids.size() < 1) {
            QueryWrapper<OrderAmazonDo> wrapper = queryBuild(map);
            orderAmazonDoList = this.baseMapper.selectList(wrapper);
        } else {
            orderAmazonDoList = baseMapper.selectBatchIds(ids);
        }
        if (orderAmazonDoList.size() > 1000) {
            response.sendError(500, "数据超过1000条，请分日期导出");
            throw new BizException(SysConstant.File_Export_ToMuch, 1000);
        }
        List<AmazonOrderExcelExportVo> excelExportVoList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(orderAmazonDoList)) {
            LambdaQueryWrapper<OrderAmazonItemsDo> itemsWrapper;
            for (OrderAmazonDo orderAmazonDo : orderAmazonDoList) {
                AmazonOrderExcelExportVo excelExportVo = new AmazonOrderExcelExportVo();
                BeanUtils.copyProperties(orderAmazonDo, excelExportVo);

                itemsWrapper = new LambdaQueryWrapper<>();
                itemsWrapper.eq(OrderAmazonItemsDo::getOrderAmazonId, orderAmazonDo.getId());
                List<OrderAmazonItemsDo> itemsDoList = orderAmazonItemsDao.selectList(itemsWrapper);

                List<AmazonOrderItemExcelExportVo> itemExcelExportVoList = new ArrayList<>();
                if (!CollectionUtils.isEmpty(itemsDoList)) {
                    for (OrderAmazonItemsDo itemsDo : itemsDoList) {
                        AmazonOrderItemExcelExportVo itemExcelExportVo = new AmazonOrderItemExcelExportVo();
                        BeanUtils.copyProperties(itemsDo, itemExcelExportVo);
                        itemExcelExportVoList.add(itemExcelExportVo);
                    }
                }

                excelExportVo.setItemExcelExportVoList(itemExcelExportVoList);

                excelExportVoList.add(excelExportVo);
            }
        }
        ExcelUtils.exportExcel(excelExportVoList, AmazonOrderExcelExportVo.class, "亚马逊订单", new ExportParams(), response);
    }

    @Override
    public SingleResult markSendOut(List<Long> ids, Long userId) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new BizException(SysConstant.Pls_Choose_Order);
        }
        for (Long id : ids) {
            OrderAmazonDo orderAmazonDo = this.baseMapper.selectById(id);
//            if (orderAmazonDo.getIsSendOut() == 0) {
            orderAmazonDo.setIsSendOut(1);
            this.baseMapper.updateById(orderAmazonDo);
            operateRecordDao.operateAddRecord(SysConstant.OPERATE_MARK_SEND, orderAmazonDo.getId(), userId, 4);
//            }
        }
        return SingleResult.success();
    }

//    private void operateRecord(String str, OrderAmazonDo orderAmazonDo, Long userId) {
//        OperateRecordDo operateRecordDo = new OperateRecordDo();
//        operateRecordDo.setContent(str);
//        operateRecordDo.setOperateTime(new Date());
//        operateRecordDo.setOperateBy(userId);
//        operateRecordDo.setType(4);
//        operateRecordDo.setThirdId(orderAmazonDo.getId());
//        operateRecordDo.setDeleteFlag(0);
//        operateRecordDao.insert(operateRecordDo);
//    }

    @Override
    public SingleResult updateSysMemo(UpdateSysMemoReq req, Long userId, Long companyId) {
        OrderAmazonDo orderAmazonDo = this.baseMapper.selectById(req.getId());
        orderAmazonDo.setSystemMemo(req.getSystemMemo());
        this.baseMapper.updateById(orderAmazonDo);
        return SingleResult.success("编辑成功", null);
    }

    @Override
    public SingleResult sendOut(String[] ids, Long userId, Long companyId, boolean isAuto) {
        List<OrderOutputAddReq> orderOutputAddReqList = new ArrayList<>();
        List<String> failOrders = new ArrayList<>();
        List<OrderAmazonDo> orderAmazonDos = this.baseMapper.selectBatchIds(Arrays.asList(ids));
        for (OrderAmazonDo orderAmazonDo : orderAmazonDos) {
            if (orderAmazonDo == null) {
                throw new BizException(SysConstant.Error_Data_NotExist);
            }
            LambdaQueryWrapper<OrderAmazonItemsDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OrderAmazonItemsDo::getOrderAmazonId, orderAmazonDo.getId());
            List<OrderAmazonItemsDo> itemsDoList = orderAmazonItemsDao.selectList(wrapper);
            //订单
            OrderOutputAddReq res = new OrderOutputAddReq();
            res.setPlatformNumber("amazon");
            res.setPlatformNumber(orderAmazonDo.getId() + "");
            res.setSendDate(new Date());
            res.setShopId(orderAmazonDo.getShopId());
            res.setCompanyId(orderAmazonDo.getCompanyId());
            res.setOrderNo(orderAmazonDo.getAmazonOrderNumber());
            res.setReceiverName(orderAmazonDo.getShipName() + " 様");
            res.setTelPhone(orderAmazonDo.getShipPhone());
            res.setPostCode(orderAmazonDo.getPostalCode());
            res.setArea(orderAmazonDo.getShipStateOrRegion());
            res.setAddress(orderAmazonDo.getShipAddress());
            if (orderAmazonDo.getLastDeliveryDate() != null && orderAmazonDo.getEarliestDeliveryDate() != null &&
                    "Scheduled".equals(orderAmazonDo.getShipmentServiceLevelCategory())) {
                try {
                    res.setDeliveryDate(TimeUtils.formatDate(orderAmazonDo.getLastDeliveryDate()));
                    res.setDeliveryTime(TimeUtils.formatDate(orderAmazonDo.getEarliestDeliveryDate(), "HH") +
                            "-" + TimeUtils.formatDate(orderAmazonDo.getLastDeliveryDate(), "HH"));
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error(e.getMessage());
                }
            }
            long storageId = 0L;
            //item
            List<OrderOutputProductAddReq> orderOutputProductDetailList = new ArrayList<>();
            List<OrderAmazonItemsDo> failedItems = new ArrayList<>();
            if (!CollectionUtils.isEmpty(itemsDoList)) {
                double[] size = new double[4];
                double shipPirce = 99999D;
                //默认仓库先捆包
                for (OrderAmazonItemsDo itemsDo : itemsDoList) {
                    Long productId = getProductId(itemsDo.getSellerSku(), orderAmazonDo.getCompanyId());
                    if (productId == null) {
                        failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Product_Notfound, orderAmazonDo.getAmazonOrderNumber(), itemsDo.getSellerSku()));
                        continue;
                    }
                    Long stateId = mRegionService.getStateIdByPostCode(orderAmazonDo.getPostalCode());
                    if (stateId <= 7) {//大阪地区优先发货仓库
                        storageId = 12L;
                    } else {//东京仓库优先发货仓库
                        storageId = 1L;
                    }
                    LambdaQueryWrapper<StockRecordDo> wrapper1 = new LambdaQueryWrapper();
                    wrapper1.eq(StockRecordDo::getShopId, res.getShopId())
                            .eq(StockRecordDo::getProductInfoId, productId)
                            .eq(StockRecordDo::getStorageId, storageId);
                    StockRecordDo stockRecordDo = stockDao.selectOne(wrapper1);
                    int noDeliveredCount = stockDao.getOrderOutCount(productId, res.getShopId(), storageId);
                    if (stockRecordDo == null || stockRecordDo.getCanSellCount() - noDeliveredCount < itemsDo.getQuantityOrdered() - itemsDo.getQuantityShipped()) {//优先仓库有库存，优先仓库发货
                        failedItems.add(itemsDo);
                        continue;
                    }
                    OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                    productDetail.setOrderId(itemsDo.getOrderAmazonId());
                    productDetail.setProductId(productId);
                    productDetail.setCount(itemsDo.getQuantityOrdered() - itemsDo.getQuantityShipped());
                    orderOutputProductDetailList.add(productDetail);
                }
                OrderOutputPackageAddReq packageDetail = new OrderOutputPackageAddReq();
                List<OrderOutputPackageAddReq> packageAddReqList = new ArrayList<>();
                packageDetail.setProductList(orderOutputProductDetailList);
                OrderOutputAddReq addReq = new OrderOutputAddReq();
                BeanUtils.copyProperties(res, addReq);
                packageAddReqList.add(packageDetail);
                addReq.setStorageId(storageId);
                addReq.setPackageList(packageAddReqList);
                //默认仓库库存不足
                if (failedItems.size() < 1 && storageId != 0L) {
                    orderOutputAddReqList.add(addReq);
                } else {
                    List<OrderOutputProductAddReq> productAddList = new ArrayList<>();
                    //剩余一件商品无库存
                    if (failedItems.size() == 1 && failedItems.get(0).getQuantityOrdered() - failedItems.get(0).getQuantityShipped() == 1) {
                        storageId = 0L;
                        Long productId = getProductId(failedItems.get(0).getSellerSku(), res.getCompanyId());
                        if (productId == null) {
                            failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Product_Notfound, orderAmazonDo.getAmazonOrderNumber(), failedItems.get(0).getSellerSku()));
                            continue;
                        }
                        int count = failedItems.get(0).getQuantityOrdered() - failedItems.get(0).getQuantityShipped();
                        List<StorageDo> storageDos = storageDao.selectList(null);
                        for (StorageDo storageDo : storageDos) {//遍历仓库是否都有库存
                            LambdaQueryWrapper<StockRecordDo> wrapper2 = new LambdaQueryWrapper();
                            wrapper2.eq(StockRecordDo::getShopId, res.getShopId())
                                    .eq(StockRecordDo::getProductInfoId, productId)
                                    .eq(StockRecordDo::getStorageId, storageDo.getId());
                            StockRecordDo stockRecordDo1 = stockDao.selectOne(wrapper2);

                            size = shipPriceService.countSameSkuSize(new double[4], productId, failedItems.get(0).getQuantityOrdered() - failedItems.get(0).getQuantityShipped());
                            int noDeliveredCount1 = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId());
                            if (stockRecordDo1 != null && stockRecordDo1.getCanSellCount() - noDeliveredCount1 >= count) {
                                List<ShipPriceDo> shipPriceDos = shipPriceService.queryByRegionAndSize(res.getPostCode(),
                                        size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], res.getCod(), res.getShipmentType(), storageDo.getId(), 1);
                                if (shipPriceDos.size() < 1 || shipPriceDos.get(0).getPrice() == 0) continue;
                                if (shipPirce > shipPriceDos.get(0).getPrice()) {//选择最便宜的价格
                                    shipPirce = shipPriceDos.get(0).getPrice();
                                    storageId = storageDo.getId();
                                }
                            }
                        }
                        OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                        productDetail.setProductId(productId);
                        productDetail.setCount(count);
                        productAddList.add(productDetail);
                        OrderOutputPackageAddReq packageDetail1 = new OrderOutputPackageAddReq();
                        if (storageId != 0) {
                            List<OrderOutputPackageAddReq> packageAddReqList1 = new ArrayList<>();
                            packageDetail1.setProductList(productAddList);
                            OrderOutputAddReq addReq1 = new OrderOutputAddReq();
                            BeanUtils.copyProperties(res, addReq1);
                            packageAddReqList1.add(packageDetail1);
                            addReq1.setStorageId(storageId);
                            addReq1.setPackageList(packageAddReqList1);
                            orderOutputAddReqList.add(addReq1);
                        }//TODO 剩一个，都没有库存
                        else {
                            failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Stock_NotEnough, orderAmazonDo.getAmazonOrderNumber(), failedItems.get(0).getSellerSku()));
                        }
                    } else {
                        //多件商品无库存，第二优先捆包
                        List<OrderAmazonItemsDo> productDoListFailed = new ArrayList<>();
                        LambdaQueryWrapper<StorageDo> lambdaQueryWrapper = new LambdaQueryWrapper();
                        lambdaQueryWrapper.eq(StorageDo::getSupportShip, 1)
                                .ne(StorageDo::getId, storageId);
                        List<StorageDo> storageDos = storageDao.selectList(lambdaQueryWrapper);
                        storageId = 0L;
                        if (storageDos != null) {
                            StorageDo storageDo = storageDos.get(0);//遍历支持捆包仓库是否都有库存
                            for (OrderAmazonItemsDo productDo :
                                    failedItems) {
                                Long productId = getProductId(productDo.getSellerSku(), res.getCompanyId());
                                if (productId == null) {
                                    failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Product_Notfound, orderAmazonDo.getAmazonOrderNumber(), productDo.getSellerSku()));
                                    continue;
                                }
                                int count = productDo.getQuantityOrdered() - productDo.getQuantityShipped();
                                LambdaQueryWrapper<StockRecordDo> wrapper1 = new LambdaQueryWrapper();
                                wrapper1.eq(StockRecordDo::getShopId, res.getShopId())
                                        .eq(StockRecordDo::getProductInfoId, productId)
                                        .eq(StockRecordDo::getStorageId, storageDo.getId());
                                StockRecordDo stockRecordDo = stockDao.selectOne(wrapper1);
                                int noDeliveredCount = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId());

                                if (stockRecordDo == null || stockRecordDo.getCanSellCount() - noDeliveredCount < count) {
                                    productDoListFailed.add(productDo);
                                    continue;
                                }
                                OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                                productDetail.setProductId(productId);
                                productDetail.setCount(count);
                                productAddList.add(productDetail);

                            }
                            packageDetail = new OrderOutputPackageAddReq();
                            List<OrderOutputPackageAddReq> packageAddReqList1 = new ArrayList<>();
                            packageDetail.setProductList(productAddList);
                            OrderOutputAddReq addReq1 = new OrderOutputAddReq();
                            BeanUtils.copyProperties(res, addReq1);
                            packageAddReqList1.add(packageDetail);
                            if (storageId != 0) {
                                addReq1.setStorageId(storageId);
                                addReq1.setPackageList(packageAddReqList1);
                                orderOutputAddReqList.add(addReq1);
                            }
                        } else {
                            productDoListFailed.addAll(failedItems);
                        }
                        //所有捆包仓库无库存的产品
                        if (productDoListFailed.size() > 0) {//捆包仓库无库存，分别发
                            LambdaQueryWrapper<StorageDo> queryWrapper = new LambdaQueryWrapper();
                            queryWrapper.eq(StorageDo::getSupportShip, 0);
                            List<StorageDo> storageDoList = storageDao.selectList(queryWrapper);
                            for (OrderAmazonItemsDo productDo :
                                    productDoListFailed) {
                                storageId = 0L;
                                shipPirce = 99999D;
                                Long productId = getProductId(productDo.getSellerSku(), res.getCompanyId());
                                int count = productDo.getQuantityOrdered() - productDo.getQuantityShipped();

                                for (StorageDo storageDo : storageDoList) {//遍历仓库是否都有库存
                                    LambdaQueryWrapper<StockRecordDo> wrapper2 = new LambdaQueryWrapper();
                                    size = shipPriceService.countSameSkuSize(new double[4], productId,
                                            1);
                                    wrapper2.eq(StockRecordDo::getShopId, res.getShopId())
                                            .eq(StockRecordDo::getProductInfoId, productId)
                                            .eq(StockRecordDo::getStorageId, storageDo.getId());
                                    StockRecordDo stockRecordDo1 = stockDao.selectOne(wrapper2);
                                    int noDeliveredCount1 = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId());
                                    if (stockRecordDo1 != null && stockRecordDo1.getCanSellCount() - noDeliveredCount1 >= count) {
                                        List<ShipPriceDo> shipPriceDos = shipPriceService.queryByRegionAndSize(res.getPostCode(),
                                                size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], res.getCod(), res.getShipmentType(), storageDo.getId(), 1);
                                        if (shipPriceDos.size() < 1 || shipPriceDos.get(0).getPrice() == 0)
                                            continue;
                                        if (shipPirce > shipPriceDos.get(0).getPrice()) {//选择最便宜的价格
                                            shipPirce = shipPriceDos.get(0).getPrice();
                                            storageId = storageDo.getId();
                                        }
                                    }
                                }
                                if (storageId != 0) {
                                    OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                                    productDetail.setProductId(productId);
                                    productDetail.setCount(productDo.getQuantityOrdered() - productDo.getQuantityShipped());
                                    productAddList.add(productDetail);
                                } else {
                                    //剩余SKU都没有库存
                                    failOrders.add(StringsUtil.createI18Message(SysConstant.OrderYahoo_Stock_NotEnough, orderAmazonDo.getAmazonOrderNumber(), failedItems.get(0).getSellerSku()));
                                }
                            }
                            packageDetail = new OrderOutputPackageAddReq();
                            packageAddReqList = new ArrayList<>();
                            packageDetail.setProductList(productAddList);
                            addReq = new OrderOutputAddReq();
                            BeanUtils.copyProperties(res, addReq);
                            packageAddReqList.add(packageDetail);
                            if (storageId != 0) {
                                addReq.setStorageId(storageId);
                                addReq.setPackageList(packageAddReqList);
                                orderOutputAddReqList.add(addReq);
                            }
                        }
                    }
                }
            }
            if (orderOutputAddReqList.size() > 0) {
                operateRecordDao.operateAddRecord(SysConstant.OPERATE_CLICK_SEND, orderAmazonDo.getId(), userId, 4);
            }
        }
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            StringBuilder sku = new StringBuilder();
            int cout = 0;
            for (OrderOutputProductAddReq orderOutputProductAddReq : outputAddReq.getPackageList().get(0).getProductList()) {
                cout = cout + orderOutputProductAddReq.getCount();
                if (StringUtils.isNotBlank(sku)) {
                    sku.append(",");
                }
                sku.append(productInfoDao.selectById(orderOutputProductAddReq.getProductId()).getCommoditySku());
            }
            outputAddReq.setSku(sku.toString());
            outputAddReq.setCount(cout);
        }
        if (isAuto) {
            sendOutMatch(orderOutputAddReqList, userId);
        }
        Map map = new HashMap();
        map.put("orderList", orderOutputAddReqList);
        map.put("failedList", failOrders);
        map.put("storageList", storageDao.selectList(null));
        return SingleResult.success(map);
    }

    @Override
    public SingleResult sendOutNopackage(String id, Long userId, Long companyId) {
        List<OrderOutputAddReq> orderOutputAddReqList = new ArrayList<>();
        List<String> failOrders = new ArrayList<>();
        OrderAmazonDo orderAmazonDo = this.baseMapper.selectById(id);
        if (orderAmazonDo == null) {
            throw new BizException(SysConstant.Error_Data_NotExist);
        }
        LambdaQueryWrapper<OrderAmazonItemsDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderAmazonItemsDo::getOrderAmazonId, id);
        List<OrderAmazonItemsDo> itemsDoList = orderAmazonItemsDao.selectList(wrapper);
        //订单
        OrderOutputAddReq res = new OrderOutputAddReq();
        res.setPlatformNumber("amazon");
        res.setPlatformNumber(orderAmazonDo.getId() + "");
        res.setSendDate(new Date());
        res.setShopId(orderAmazonDo.getShopId());
        res.setCompanyId(orderAmazonDo.getCompanyId());
        res.setOrderNo(orderAmazonDo.getAmazonOrderNumber());
        res.setReceiverName(orderAmazonDo.getShipName());
        res.setTelPhone(orderAmazonDo.getShipPhone());
        res.setPostCode(orderAmazonDo.getPostalCode());
        res.setArea(orderAmazonDo.getShipStateOrRegion());
        res.setAddress(orderAmazonDo.getShipAddress());
        //item
        List<OrderOutputProductAddReq> orderOutputProductDetailList = new ArrayList<>();
        LambdaQueryWrapper<StorageDo> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(StorageDo::getSupportShip, 0);
        List<StorageDo> storageDoList = storageDao.selectList(queryWrapper);
        for (OrderAmazonItemsDo productDo :
                itemsDoList) {
            long storageId = 0L;
            double shipPirce = 99999D;
            int count = productDo.getQuantityOrdered() - productDo.getQuantityShipped();

            Long productId = getProductId(productDo.getSellerSku(), res.getCompanyId());
            for (StorageDo storageDo : storageDoList) {//遍历仓库是否都有库存
                LambdaQueryWrapper<StockRecordDo> wrapper2 = new LambdaQueryWrapper();
                double[] size = shipPriceService.countSameSkuSize(new double[4], productId,
                        1);
                wrapper2.eq(StockRecordDo::getShopId, res.getShopId())
                        .eq(StockRecordDo::getProductInfoId, productId)
                        .eq(StockRecordDo::getStorageId, storageDo.getId());
                StockRecordDo stockRecordDo1 = stockDao.selectOne(wrapper2);
                int noDeliveredCount1 = stockDao.getOrderOutCount(productId, res.getShopId(), storageDo.getId());
                if (stockRecordDo1 != null && stockRecordDo1.getCanSellCount() - noDeliveredCount1 >= count) {
                    List<ShipPriceDo> shipPriceDos = shipPriceService.queryByRegionAndSize(res.getPostCode(),
                            size[3], size[0] + size[1] + size[2], size[0], size[1], size[2], res.getCod(), res.getShipmentType(), storageDo.getId(), 1);
                    if (shipPriceDos.size() < 1 || shipPriceDos.get(0).getPrice() == 0) continue;
                    if (shipPirce > shipPriceDos.get(0).getPrice()) {//选择最便宜的价格
                        shipPirce = shipPriceDos.get(0).getPrice();
                        storageId = storageDo.getId();
                    }
                }
            }
            if (storageId != 0) {
                OrderOutputProductAddReq productDetail = new OrderOutputProductAddReq();
                productDetail.setProductId(productId);
                productDetail.setCount(productDo.getQuantityOrdered() - productDo.getQuantityShipped());
                List<OrderOutputProductAddReq> productAddList = new ArrayList<>();
                productAddList.add(productDetail);
                OrderOutputPackageAddReq packageDetail = new OrderOutputPackageAddReq();
                List<OrderOutputPackageAddReq> packageAddReqList = new ArrayList<>();
                packageDetail.setProductList(productAddList);
                OrderOutputAddReq addReq = new OrderOutputAddReq();
                BeanUtils.copyProperties(res, addReq);
                packageAddReqList.add(packageDetail);
                if (storageId != 0) {
                    addReq.setStorageId(storageId);
                    addReq.setPackageList(packageAddReqList);
                    orderOutputAddReqList.add(addReq);
                }
            } else {
                //剩余SKU都没有库存
                failOrders.add(String.format("%s(%s库存不足)", orderAmazonDo.getAmazonOrderNumber(), productDo.getSellerSku()));
            }

        }

        if (orderOutputAddReqList.size() > 0) {
            operateRecordDao.operateAddRecord(SysConstant.OPERATE_CLICK_SEND, orderAmazonDo.getId(), userId, 4);
        }
        for (OrderOutputAddReq outputAddReq : orderOutputAddReqList) {
            StringBuilder sku = new StringBuilder();
            int cout = 0;
            for (OrderOutputProductAddReq orderOutputProductAddReq : outputAddReq.getPackageList().get(0).getProductList()) {
                cout = cout + orderOutputProductAddReq.getCount();
                if (StringUtils.isNotBlank(sku)) {
                    sku.append(",");
                }
                sku.append(productInfoDao.selectById(orderOutputProductAddReq.getProductId()).getCommoditySku());
            }
            outputAddReq.setSku(sku.toString());
            outputAddReq.setCount(cout);
        }
        Map map = new HashMap();
        map.put("orderList", orderOutputAddReqList);
        map.put("failedList", failOrders);
        map.put("storageList", storageDao.selectList(null));
        return SingleResult.success(map);
    }

    @Override
    public SingleResult sendOutMatch(List<OrderOutputAddReq> orderOutputAddReqList, Long userId) {
        List<String> failOrders = orderOutputService.addAmazonList(orderOutputAddReqList, userId);
        if (failOrders.size() > 0) {
//            return SingleResult.failure("300", String.format("成功导出%d个发货单", orderOutputAddReqList.size() - failOrders.size()), failOrders);
            return SingleResult.failure("300", SysConstant.OrderYahoo_Export_Success, failOrders, orderOutputAddReqList.size() - failOrders.size());

        } else {
            return SingleResult.success(failOrders);
        }
    }

    private Long getProductId(String sellerSku, Long companyId) {
        QueryWrapper productWrapper = new QueryWrapper();
        productWrapper.eq("commodity_sku", sellerSku);
        productWrapper.eq("company_id", companyId);
        ProductInfoDo productInfoDo = productInfoDao.selectOne(productWrapper);
        if (productInfoDo == null) {
            QueryWrapper skuWrapper = new QueryWrapper();
            skuWrapper.eq("sub_sku", sellerSku);
            skuWrapper.eq("company_id", companyId);
            ProductSkuMapDo productSkuMapDo = productSkuMapDao.selectOne(skuWrapper);
            if (productSkuMapDo == null) return null;
            return productSkuMapDo.getProductInfoId();
        } else {
            return productInfoDo.getId();
        }
    }


    private OrderOutputPackageAddReq handlerPackage(List<OrderOutputProductAddReq> productInfoDoList) {
        OrderOutputPackageAddReq packageDetail = new OrderOutputPackageAddReq();
//        Float length = 0F;
//        Float width = 0F;
//        Float height = 0F;
//        Float weight = 0F;
//        if (!CollectionUtils.isEmpty(productInfoDoList)) {
//            for (ProductInfoDo productInfoDo : productInfoDoList) {
//                if (productInfoDo.getLength() > length) {
//                    length = productInfoDo.getLength();
//                }
//                if (productInfoDo.getWidth() > width) {
//                    width = productInfoDo.getWidth();
//                }
//                if (productInfoDo.getHeight() > height) {
//                    height = productInfoDo.getHeight();
//                }
//                weight += productInfoDo.getWeight();
//            }
//        }
//        Float volume = length * width * height;
//
//        packageDetail.setHeight(height.doubleValue());
//        packageDetail.setLength(length.doubleValue());
//        packageDetail.setWidth(width.doubleValue());
//        packageDetail.setWeight(weight.doubleValue());
//        packageDetail.setTrackId(null);
        //todo
        return packageDetail;
    }

    private void handlerOderInsert(Long shopId,
                                   Long companyId, OrderAmazonDo orderAmazonDo, ListOrdersResult.ListOrdersResultEntity.OrdersEntity.OrderEntity
                                           orderEntity, OrderItemsResponse
                                           itemsResponse) {
        if (orderAmazonDo == null)
            orderAmazonDo = new OrderAmazonDo();
        orderAmazonDo.setAmazonOrderNumber(orderEntity.getAmazonOrderId());
        orderAmazonDo.setPurchaseDate(TimeUtils.getDateTime(orderEntity.getPurchaseDate()));  //2020-05-02T14:59:59Z
        orderAmazonDo.setLastUpdateDate(TimeUtils.getDateTime(orderEntity.getLastUpdateDate()));  //2020-05-02T14:59:59Z
        orderAmazonDo.setOrderStatus(orderEntity.getOrderStatus());
        orderAmazonDo.setFulfillmentChannel(orderEntity.getFulfillmentChannel());
        orderAmazonDo.setSalesChannel(orderEntity.getSalesChannel());
        orderAmazonDo.setShipServiceLevel(orderEntity.getShipServiceLevel());
        try {
            orderAmazonDo.setShipAddress(getStr(orderEntity.getShippingAddress().get(0).getAddressLine1()) + getStr(orderEntity.getShippingAddress().get(0).getAddressLine2()) + getStr(orderEntity.getShippingAddress().get(0).getAddressLine3()));
        } catch (Exception e) {
            log.error("Amazon地址转换错误" + e.getMessage());
        }
        orderAmazonDo.setSellerOrderNumber(orderEntity.getSellerOrderId());
        orderAmazonDo.setOrderChannel(orderEntity.getOrderChannel());
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipName(orderEntity.getShippingAddress().get(0).getName());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipCity(orderEntity.getShippingAddress().get(0).getCity());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipCounty(orderEntity.getShippingAddress().get(0).getCounty());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipDistrict(orderEntity.getShippingAddress().get(0).getDistrict());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipStateOrRegion(orderEntity.getShippingAddress().get(0).getStateOrRegion());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setPostalCode(orderEntity.getShippingAddress().get(0).getPostalCode()); //ship
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipPhone(orderEntity.getShippingAddress().get(0).getPhone());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getShippingAddress())) {
            orderAmazonDo.setShipAddressType(orderEntity.getShippingAddress().get(0).getAddressType());
        }
        if (!CollectionUtils.isEmpty(orderEntity.getOrderTotal())) {
            orderAmazonDo.setOrderTotal(orderEntity.getOrderTotal().get(0).getAmount()); //OrderTotalEntity
        }

        orderAmazonDo.setShipmentServiceLevelCategory(orderEntity.getShipmentServiceLevelCategory());
        orderAmazonDo.setPaymentMethod(orderEntity.getPaymentMethod());
        if ("COD".equals(orderEntity.getPaymentMethod())) {
            if (orderEntity.getPaymentExecutionDetail().size() > 0) {
                double sum = orderEntity.getPaymentExecutionDetail().stream().mapToDouble(paymentMethodDetailsEntity -> {
                    if (paymentMethodDetailsEntity.getPayment() != null &&
                            StringUtils.isNotBlank(paymentMethodDetailsEntity.getPayment().getAmount())) {
                        return Double.parseDouble(paymentMethodDetailsEntity.getPayment().getAmount());
                    } else {
                        return 0;
                    }
                }).sum();
                orderAmazonDo.setPaymentCod(String.valueOf(sum));
            }
        }
        orderAmazonDo.setBuyerEmail(orderEntity.getBuyerEmail());
        orderAmazonDo.setBuyerName(orderEntity.getBuyerName());
        orderAmazonDo.setOrderType(orderEntity.getOrderType());
        orderAmazonDo.setEarliestShipDate(TimeUtils.getDateTime2(orderEntity.getEarliestShipDate()));
        orderAmazonDo.setLastShipDate(TimeUtils.getDateTime2(orderEntity.getLatestShipDate()));
        orderAmazonDo.setEarliestDeliveryDate(TimeUtils.getDateTime2(orderEntity.getEarliestDeliveryDate()));
        orderAmazonDo.setLastDeliveryDate(TimeUtils.getDateTime2(orderEntity.getLatestDeliveryDate()));
        orderAmazonDo.setPurchaseOrderNumber(orderEntity.getPurchaseOrderNumber());
        orderAmazonDo.setShopId(shopId);
        orderAmazonDo.setCompanyId(companyId);
        StringBuilder sb = new StringBuilder();
        if (itemsResponse != null) {
            for (OrderItemsResponse.ListOrderItemsResultEntity.OrderItemsEntity.OrderItemEntity itemEntity : itemsResponse.getListOrderItemsResult().get(0).getOrderItems().get(0).getOrderItem()) {
                if (sb.length() > 1) {
                    sb.append(",");
                }
                if (shopId == 1) {
                    sb.append(itemEntity.getSellerSKU().replaceAll("BFBA-", "").replaceAll("FBA-", ""));
                } else {
                    sb.append(itemEntity.getSellerSKU());
                }
            }
            orderAmazonDo.setCommoditySku(sb.toString());
        }

        if (orderAmazonDo.getId() == null || orderAmazonDo.getId() == 0) {
            dao.insert(orderAmazonDo);
        } else {
            dao.updateById(orderAmazonDo);
        }
        if (itemsResponse == null) {
            return;
        }

        for (OrderItemsResponse.ListOrderItemsResultEntity.OrderItemsEntity.OrderItemEntity itemEntity :
                itemsResponse.getListOrderItemsResult().get(0).getOrderItems().get(0).getOrderItem()) {
            OrderAmazonItemsDo itemsDo = new OrderAmazonItemsDo();
            itemsDo.setOrderAmazonId(orderAmazonDo.getId());
            itemsDo.setAsin(itemEntity.getASIN());
            if (shopId == 1) {
                itemsDo.setSellerSku(itemEntity.getSellerSKU().replaceAll("BFBA-", "").replaceAll("FBA-", ""));
            } else {
                itemsDo.setSellerSku(itemEntity.getSellerSKU());
            }
            Long productId = getProductId(itemsDo.getSellerSku(), companyId);
            itemsDo.setSystemSku(productId);
            itemsDo.setTitle(itemEntity.getTitle());
            try {
                itemsDo.setQuantityOrdered(Integer.parseInt(itemEntity.getQuantityOrdered()));
                itemsDo.setQuantityShipped(Integer.parseInt(itemEntity.getQuantityShipped()));
            } catch (Exception e) {
                log.error(e.getMessage());
            }
            if (!CollectionUtils.isEmpty(itemEntity.getItemPrice())) {
                itemsDo.setItemPrice(itemEntity.getItemPrice().get(0).getAmount());
            }
            if (!CollectionUtils.isEmpty(itemEntity.getCODFee())) {
                itemsDo.setCodFee(itemEntity.getCODFee().get(0).getAmount());
            }
            itemsDo.setItemId(itemEntity.getOrderItemId());
            itemsDo.setIsGift(StringUtils.isNotBlank(itemEntity.getIsGift()) && "true".equals(itemEntity.getIsGift()) ? 1 : 0);
            QueryWrapper wrapper1 = new QueryWrapper();
            wrapper1.eq("item_id", itemsDo.getItemId());
            OrderAmazonItemsDo amazonItemsDo = orderAmazonItemsDao.selectOne(wrapper1);
            if (amazonItemsDo == null) {
                orderAmazonItemsDao.insert(itemsDo);
            } else {
                itemsDo.setId(amazonItemsDo.getId());
                orderAmazonItemsDao.updateById(itemsDo);
            }

        }


    }

    @Override
    public Object add(Object req, Long userId) {
        OrderAmazonDo entityDo = new OrderAmazonDo();
        BeanUtils.copyProperties(req, entityDo);
        handlerAddBefore(entityDo, userId);
        dao.insert(entityDo);
        return handlerAddAfter(entityDo);
    }

    //新增校验
    private void addCheck(Object req) {

    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(OrderAmazonDo entityDo, Long userId) {
//        entityDo.setCreateBy(userId);
//        entityDo.setCreateTime(new Date());
//        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(OrderAmazonDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }


    @Override
    public int delete(Long id, Long userId) {
        OrderAmazonDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(OrderAmazonDo entityDo, Long userId) {
//        entityDo.setDeleteBy(userId);
//        entityDo.setDeleteTime(new Date());
    }

    @Override
    public AmazonOrderDetailRes detail(Long id) {
        AmazonOrderDetailRes res = new AmazonOrderDetailRes();
        OrderAmazonDo amazonDo = dao.selectById(id);
        BeanUtils.copyProperties(amazonDo, res);
        LambdaQueryWrapper<OrderAmazonItemsDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderAmazonItemsDo::getOrderAmazonId, id);
        List<OrderAmazonItemsDo> itemsDoList = orderAmazonItemsDao.selectList(wrapper);
        List<AmazonOrderProductRes> productResList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(itemsDoList)) {
            for (OrderAmazonItemsDo itemsDo : itemsDoList) {
                AmazonOrderProductRes productRes = new AmazonOrderProductRes();
                BeanUtils.copyProperties(itemsDo, productRes);
                productResList.add(productRes);
            }
        }
        res.setProductResList(productResList);

        List<OperateRes> operateResList = operateRecordDao.getOperateList(id, 4);
        res.setOperateResList(operateResList);

        return res;
    }

    @Override
    public SingleResult pageInit() {
        return SingleResult.success("");
    }


    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<OrderAmazonDo> wrapper = queryBuild(map);
        IPage<OrderAmazonDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<AmazonOrderPageRes> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<AmazonOrderPageRes> handlerListAfter(List<OrderAmazonDo> list) {
        List<AmazonOrderPageRes> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (OrderAmazonDo amazonDo : list) {
                AmazonOrderPageRes res = new AmazonOrderPageRes();
                BeanUtils.copyProperties(amazonDo, res);
                res.setShipAddress((StringUtils.isBlank(amazonDo.getShipStateOrRegion()) ? "" : amazonDo.getShipStateOrRegion()) + (StringUtils.isBlank(amazonDo.getShipAddress()) ? "" : amazonDo.getShipAddress()));
                CompanyDo companyDo = companyDao.selectById(amazonDo.getCompanyId());
                if (companyDo != null) {
                    res.setCompanyCode(companyDo.getCompanyCode());
                }
                result.add(res);
            }
        }
        return result;
    }

    private IPage<OrderAmazonDo> pageInit(Map<String, String> map) {
        IPage<OrderAmazonDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<OrderAmazonDo> queryBuild(Map<String, String> map) {
        QueryWrapper<OrderAmazonDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.and(i -> i.like("amazon_order_number", map.get("keyword"))
                    .or().like("ship_name", map.get("keyword"))
                    .or().like("ship_phone", map.get("keyword")));
        }
        if (StringUtils.isNotBlank(map.get("startTime"))) {
            wrapper.gt("purchase_date", map.get("startTime"));
        }
        if (StringUtils.isNotBlank(map.get("endTime"))) {
            wrapper.lt("purchase_date", map.get("endTime"));
        }
        if (StringUtils.isNotBlank(map.get("orderStatus"))) {
            wrapper.eq("order_status", map.get("orderStatus"));
        }
        if (StringUtils.isNotBlank(map.get("fulfillmentChannel"))) {
            wrapper.eq("fulfillment_channel", map.get("fulfillmentChannel"));
        }
        if (StringUtils.isNotBlank(map.get("isSendOut"))) {
            wrapper.eq("is_send_out", map.get("isSendOut"));
        }
        if (StringUtils.isNotBlank(map.get("shopId"))) {
            wrapper.eq("shop_id", map.get("shopId"));
        }
        if (StringUtils.isNotBlank(map.get("companyId"))) {
            wrapper.eq("company_id", map.get("companyId"));
        }
        return wrapper.orderByDesc("last_update_date");
    }


    private String getStr(String str) {
        if (str == null) {
            return "";
        }
        return str;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//事务回滚
    public List<OrderFulfillment> dealWithAmazonOrder(OrderOutputDo sendOutEntity) {
        LambdaQueryWrapper<OrderAmazonDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderAmazonDo::getAmazonOrderNumber, sendOutEntity.getOrderNo());
        wrapper.eq(OrderAmazonDo::getOrderStatus, "UnShipped");
        wrapper.eq(OrderAmazonDo::getShopId, sendOutEntity.getShopId());
        wrapper.eq(OrderAmazonDo::getCompanyId, sendOutEntity.getCompanyId());
        List<OrderAmazonDo> orderEntitys = baseMapper.selectList(wrapper);
        OrderAmazonDo orderEntity = null;
        if (orderEntitys.size() == 1) {
            orderEntity = orderEntitys.get(0);
        } else if (orderEntitys.size() > 1) {
            orderEntity = orderEntitys.get(orderEntitys.size() - 1);
        }
        if (orderEntity == null) {
            return null;
        }
        List<OrderFulfillment> orderFulfillmentList = new ArrayList<>();
        LambdaQueryWrapper<OrderAmazonItemsDo> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.eq(OrderAmazonItemsDo::getOrderAmazonId, orderEntity.getId());
        List<OrderAmazonItemsDo> saleOrderSkus = orderAmazonItemsDao.selectList(itemWrapper);
        if (saleOrderSkus == null || saleOrderSkus.size() < 1) return null;
        LambdaQueryWrapper<OrderOutputDo> outOrderWrappr = new LambdaQueryWrapper<>();
        outOrderWrappr.eq(OrderOutputDo::getOrderNo, sendOutEntity.getOrderNo());
        outOrderWrappr.eq(OrderOutputDo::getShopId, sendOutEntity.getShopId());
        outOrderWrappr.eq(OrderOutputDo::getCompanyId, sendOutEntity.getCompanyId());
        List<OrderOutputDo> orderOutEntityList = orderOutputService.list(outOrderWrappr);


        if (sendOutEntity.getCompanyId() == 1) {
            for (int i = 0; i < orderOutEntityList.size(); i++) {
                OrderOutputDo orderOutputDo = orderOutEntityList.get(i);
                LambdaQueryWrapper<OrderOutputPackageDetailDo> outPackageDetailWrappr = new LambdaQueryWrapper<>();
                outPackageDetailWrappr.eq(OrderOutputPackageDetailDo::getOrderOutputId, orderOutputDo.getId());
                List<OrderOutputPackageDetailDo> orderPackageDetailList = orderOutputPackageDetailDao.selectList(outPackageDetailWrappr);
                if (orderPackageDetailList.size() <= 1) {
                    OrderFulfillment orderFulfillment = buildFulfillmentEntity(orderOutputDo, orderEntity, saleOrderSkus, orderOutEntityList.size() > 1);
                    orderFulfillmentList.add(orderFulfillment);
                } else {
                    for (OrderOutputPackageDetailDo detailDo : orderPackageDetailList) {
                        OrderFulfillment orderFulfillment = buildFulfillmentEntityByPackageDetail(orderOutputDo, detailDo, orderEntity, saleOrderSkus, true);
                        orderFulfillmentList.add(orderFulfillment);
                    }
                }
            }
        } else {
            if (saleOrderSkus.size() > 1 && orderOutputService.count(outOrderWrappr) > 1) {
                for (int i = 0; i < orderOutEntityList.size(); i++) {
                    OrderFulfillment orderFulfillment = buildFulfillmentEntity(orderOutEntityList.get(i), orderEntity, saleOrderSkus, true);
                    orderFulfillmentList.add(orderFulfillment);
                }
            } else {
                OrderFulfillment orderFulfillment = buildFulfillmentEntity(sendOutEntity, orderEntity, saleOrderSkus, false);
                orderFulfillmentList.add(orderFulfillment);
            }
        }
        return orderFulfillmentList;
    }

    private OrderFulfillment buildFulfillmentEntity(OrderOutputDo sendOutEntity, OrderAmazonDo orderEntity,
                                                    List<OrderAmazonItemsDo> saleOrderSkus, boolean isMatchSku) {
        OrderFulfillment orderFulfillment = new OrderFulfillment();
        orderFulfillment.setAmazonOrderID(orderEntity.getAmazonOrderNumber());
        orderFulfillment.setFulfillmentDate(TimeUtils.formatDate(sendOutEntity.getUpdateTime(), "yyyy-MM-dd HH:mm:ss.SSS").replace(" ", "T") + "+08:00");
        if ("COD".equals(orderEntity.getPaymentMethod())) {
            orderFulfillment.setCODCollectionMethod("DirectPayment");
        }
        OrderFulfillment.FulfillmentData fulfillmentData = new OrderFulfillment.FulfillmentData();
        if (sendOutEntity.getTrackId() == DicBusinessItemConstant.sagawaExpress) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("佐川急便");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("SAGAWA EXPRESS");
                fulfillmentData.setShippingMethod("佐川急便 Hikyaku Large Size Express");
            }
        } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.yamatoExpress ||
                sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressNew) ||
                sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox) ||
                sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("ヤマト運輸");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("YAMATO TRANSPORT");
                if (sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
                    fulfillmentData.setShippingMethod("Nekopos");
                } else {
                    fulfillmentData.setShippingMethod("TA-Q-BIN");
                }
            }

        } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpress
                || sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCod
                || sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCom) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("日本郵便");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("Japan Post");
                if (sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpress) {
                    fulfillmentData.setShippingMethod("Yu-Packet");
                } else {
                    fulfillmentData.setShippingMethod("Yu-Pack");
                }
            }

        } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.xinongExpress) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("西濃運輸");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("SEINO TRANSPORTATION");
                fulfillmentData.setShippingMethod("カンガルーSAVE急便");
            }
        }
//        if (sendOutEntity.getShipmentType() == 1) {
//            fulfillmentData.setShippingMethod("マケプレお急ぎ便");
//        }
        fulfillmentData.setShipperTrackingNumber(sendOutEntity.getTrackNumber());
        List<OrderFulfillment.Item> items = new ArrayList<>();
        for (int i = 0; i < saleOrderSkus.size(); i++) {
            OrderAmazonItemsDo orderSku = saleOrderSkus.get(i);
            if (!isMatchSku ||
                    orderSku.getSellerSku().contains(sendOutEntity.getCommoditySku()) ||
                    sendOutEntity.getCommoditySku().contains(orderSku.getSellerSku()) ||
                    orderSku.getSellerSku().equals(sendOutEntity.getCommoditySku())) {
                OrderFulfillment.Item itemdata = new OrderFulfillment.Item();
                itemdata.setAmazonOrderItemCode(orderSku.getItemId() + "");
                itemdata.setMerchantFulfillmentItemID(String.valueOf(i + 1));
                itemdata.setQuantity(String.valueOf(orderSku.getQuantityOrdered() - orderSku.getQuantityShipped()));
                items.add(itemdata);
            }
        }
        orderFulfillment.setItem(items);
        orderFulfillment.setFulfillmentData(fulfillmentData);
        return orderFulfillment;
    }

    private OrderFulfillment buildFulfillmentEntityByPackageDetail(OrderOutputDo sendOutEntity, OrderOutputPackageDetailDo packageDetailDo, OrderAmazonDo orderEntity,
                                                                   List<OrderAmazonItemsDo> saleOrderSkus, boolean isMatchSku) {
        OrderFulfillment orderFulfillment = new OrderFulfillment();
        orderFulfillment.setAmazonOrderID(orderEntity.getAmazonOrderNumber());
        orderFulfillment.setFulfillmentDate(TimeUtils.formatDate(sendOutEntity.getUpdateTime(), "yyyy-MM-dd HH:mm:ss.SSS").replace(" ", "T") + "+08:00");
        if ("COD".equals(orderEntity.getPaymentMethod())) {
            orderFulfillment.setCODCollectionMethod("DirectPayment");
        }
        OrderFulfillment.FulfillmentData fulfillmentData = new OrderFulfillment.FulfillmentData();
        if (sendOutEntity.getTrackId() == DicBusinessItemConstant.sagawaExpress) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("佐川急便");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("SAGAWA EXPRESS");
                fulfillmentData.setShippingMethod("佐川急便 Hikyaku Large Size Express");
            }
        } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.yamatoExpress ||
                sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressNew) ||
                sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressBox) ||
                sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("ヤマト運輸");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("YAMATO TRANSPORT");
                if (sendOutEntity.getTrackId().equals(DicBusinessItemConstant.yamatoExpressSmall)) {
                    fulfillmentData.setShippingMethod("Nekopos");
                } else {
                    fulfillmentData.setShippingMethod("TA-Q-BIN");
                }
            }

        } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpress
                || sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCod
                || sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpressCom) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("日本郵便");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("Japan Post");
                if (sendOutEntity.getTrackId() == DicBusinessItemConstant.jpostExpress) {
                    fulfillmentData.setShippingMethod("Yu-Packet");
                } else {
                    fulfillmentData.setShippingMethod("Yu-Pack");
                }
            }

        } else if (sendOutEntity.getTrackId() == DicBusinessItemConstant.xinongExpress) {
            if (orderEntity.getShopId() > 0) {
                fulfillmentData.setCarrierName("西濃運輸");
                fulfillmentData.setShippingMethod("通常配送");
            } else {
                fulfillmentData.setCarrierCode("SEINO TRANSPORTATION");
                fulfillmentData.setShippingMethod("カンガルーSAVE急便");
            }
        }
//        if (sendOutEntity.getShipmentType() == 1) {
//            fulfillmentData.setShippingMethod("マケプレお急ぎ便");
//        }
        fulfillmentData.setShipperTrackingNumber(packageDetailDo.getTrackNumber());
        List<OrderFulfillment.Item> items = new ArrayList<>();
        for (int i = 0; i < saleOrderSkus.size(); i++) {
            OrderAmazonItemsDo orderSku = saleOrderSkus.get(i);
            String[] split = packageDetailDo.getInSkuId().split(",");
            if (split == null || split.length < 1) {
                break;
            }
            for (String skuId : split) {
                if (StringUtils.isNotBlank(skuId)) {
                    ProductInfoDo productInfoDo = productInfoDao.selectById(skuId);
                    if (productInfoDo == null) continue;
                    List<ProductSkuMapDo> productSkuMapDos = productSkuMapDao.selectList(new LambdaQueryWrapper<ProductSkuMapDo>().eq(ProductSkuMapDo::getProductInfoId, skuId));
                    List<String> collect = new ArrayList<>();
                    if (productSkuMapDos != null) {
                        collect = productSkuMapDos.stream().map(ProductSkuMapDo::getSubSku).collect(Collectors.toList());
                    }
                    if (!isMatchSku ||
                            orderSku.getSellerSku().equals(productInfoDo.getCommoditySku()) ||
                            productInfoDo.getCommoditySku().equals(orderSku.getSellerSku()) ||
                            collect.contains(orderSku.getSellerSku())) {
                        OrderFulfillment.Item itemdata = new OrderFulfillment.Item();
                        itemdata.setAmazonOrderItemCode(orderSku.getItemId() + "");
                        itemdata.setMerchantFulfillmentItemID(String.valueOf(i + 1));
                        itemdata.setQuantity(String.valueOf(orderSku.getQuantityOrdered() - orderSku.getQuantityShipped()));
                        items.add(itemdata);
                    }
                }
            }
        }
        orderFulfillment.setItem(items);
        orderFulfillment.setFulfillmentData(fulfillmentData);
        return orderFulfillment;
    }

    @Override
    public OrderSPFulfillment dealWithAmazonOrderSP(OrderOutputDo sendOutEntity) {
        return null;
    }

    @Override
    public void uploadExpressNo2Amazon(Map<Long, List<OrderFulfillment>> orderFulfillments) {
        List<String> orderIds = new ArrayList<>();
        //***亚马逊提供密钥***
        for (Map.Entry<Long, List<OrderFulfillment>> integerListEntry : orderFulfillments.entrySet()) {
            ShopDo shopBean = shopDao.selectById(integerListEntry.getKey());
            if (shopBean.getAmzSpLwa() != null) {
                threadPoolTaskExecutor.execute(() -> {
                    uploadFeeds(integerListEntry);
                });
            } else if (shopBean.getAmazonSellerId() != null && shopBean.getAmazonToken() != null) {
                HashMap<String, String> parameters = new HashMap<>();
                //***亚马逊提供访问id***
                String secretKey;
                if (shopBean.getId() == 1) {
                    parameters.put("AWSAccessKeyId", AmazonUtil.urlEncode(GlobalConstants.accessKey));
                    secretKey = GlobalConstants.secretKey;
                } else if (shopBean.getId() == 19) {
                    parameters.put("AWSAccessKeyId", GlobalConstants.accessKey1014);
                    secretKey = GlobalConstants.secretKey1014;
                } else {
                    parameters.put("AWSAccessKeyId", AmazonUtil.urlEncode(GlobalConstants.amazonAccessKey));
                    secretKey = GlobalConstants.amazonSecret;
                }
                //***商家提供授权token***
                parameters.put("MWSAuthToken", AmazonUtil.urlEncode(shopBean.getAmazonToken()));
                //***商家提供卖家id***
                parameters.put("SellerId", AmazonUtil.urlEncode(shopBean.getAmazonSellerId()));
                parameters.put("MarketplaceId.Id.1", GlobalConstants.marketplaceId);
                String requestBody = "";
                List<AmzSubmitFeedMessage> messageList = new ArrayList<>();
                for (int i = 0; i < integerListEntry.getValue().size(); i++) {
                    AmzSubmitFeedMessage message = new AmzSubmitFeedMessage();
                    message.setMessageID(String.valueOf(i + 1));
                    message.setOperationType("Update");
                    OrderFulfillment orderFulfillment = integerListEntry.getValue().get(i);
                    message.setOrderFulfillment(orderFulfillment);
                    orderIds.add(orderFulfillment.getAmazonOrderID());
                    messageList.add(message);
                }
                requestBody = XmlUtils.convertToXml(messageList, "<AmazonEnvelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
                        "xsi:noNamespaceSchemaLocation=\"amzn-envelope.xsd\">\n<Header>\n" +
                        " <DocumentVersion>1.01</DocumentVersion>\n" +
                        " <MerchantIdentifier>" + shopBean.getAmazonSellerId() + "</MerchantIdentifier>\n" +
                        " </Header>\n<MessageType>OrderFulfillment</MessageType>", "</AmazonEnvelope>");
                String body = null;
                log.info(requestBody);
                try {
                    body = AmazonUtil.doPostSubmitFeed(GlobalConstants.AmazonURL, parameters, secretKey, requestBody);
                    if (orderIds.size() > 0)
                        dao.updateOrderUploadTrack(orderIds);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error(e.getMessage());
                }
                log.info(body);
            }
        }
    }

    @Override
    public void autoRefreshOrder() {
        List<ShopDo> shopBeans = shopService.list();
        for (ShopDo shop : shopBeans) {
            if (shop.getAmazonToken() != null || shop.getAmzSpLwa() != null) {
                AmazonOrderDownReq amazonOrderDownReq = new AmazonOrderDownReq();
                amazonOrderDownReq.setBeforeDate(TimeUtils.parseDate(TimeUtils.getAfterTimeFormat("yyyy-MM-dd HH:mm:ss", -5, 0), "yyyy-MM-dd HH:mm:ss"));
                amazonOrderDownReq.setShopId(shop.getId());
                if (shop.getAmzSpLwa() != null) {
                    try {
                        downloadAmazonOrdersSP(amazonOrderDownReq);
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error(e.getMessage());
                    }
                } else if (shop.getAmazonSellerId() != null && shop.getAmazonToken() != null) {
                    try {
                        downloadAmazonOrders(amazonOrderDownReq, 0L, shop.getCompanyId());
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error(e.getMessage());
                    }
                }
            }
        }
    }


    /**
     * 把提交模板申请
     *
     * @param feedDocumentId 模板id
     * @param accessToken    token
     * @return
     */
    private String createFeed(String feedDocumentId, String accessToken) {
        try {
            Map parametersMap = new HashMap<>();
            List<String> marketplaceIds = new ArrayList<>();
            marketplaceIds.add(GlobalConstants.marketplaceId);
            parametersMap.put("feedType", "POST_ORDER_FULFILLMENT_DATA");
            parametersMap.put("marketplaceIds", marketplaceIds);
            parametersMap.put("inputFeedDocumentId", feedDocumentId);
            System.out.println(SHA256Utils.getSHA256(JSON.toJSONString(parametersMap)));
            log.info(JSONObject.toJSONString(parametersMap));
            String body = AmazonUtil.spAPidoPOST("https://sellingpartnerapi-fe.amazon.com/feeds/2021-06-30/feeds",
                    accessToken, getAwsSTSSessionToken(), parametersMap, JSON.toJSONString(parametersMap));
            log.info(body);
            return JSONObject.parseObject(body).getString("feedId");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 根据模板提交文件查询进度
     *
     * @param feedId
     * @param orderIds
     * @return
     */
    @Override
    public String getFeed(String feedId, String accessToken, String sessionToken, List<String> orderIds) {
        //51207018773
        try {
            Thread.sleep(30 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Map parametersMap = new HashMap<>();
        System.out.println(SHA256Utils.getSHA256(JSON.toJSONString(parametersMap)));
        log.info(JSONObject.toJSONString(parametersMap));
        try {
            String result = AmazonUtil.spAPidoGet("https://sellingpartnerapi-fe.amazon.com/feeds/2021-06-30/feeds/" + feedId,
                    accessToken, sessionToken, parametersMap, "");
            log.info(result);
            JSONObject jsonObject = JSON.parseObject(result);
            if (jsonObject.getJSONArray("errors") != null) {

            } else if ("DONE".equals(jsonObject.getString("processingStatus"))) {
                String resultFeedDocumentId = jsonObject.getString("resultFeedDocumentId");
                getDocument("feeds/2021-06-30/documents/", resultFeedDocumentId, accessToken, sessionToken, orderIds);
            } else if ("IN_PROGRESS".equals(jsonObject.getString("processingStatus")) ||
                    "IN_QUEUE".equals(jsonObject.getString("processingStatus"))) {
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                getFeed(feedId, accessToken, sessionToken, orderIds);
            } else {

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getDocument(String path, String feedDocumentId, String accessToken, String sessionToken, List<String> orderIds) {
        Map parametersMap = new HashMap<>();
        String body = null;
        try {
            body = AmazonUtil.spAPidoGet("https://sellingpartnerapi-fe.amazon.com/" + path + feedDocumentId,
                    accessToken, sessionToken, parametersMap, "");
            CreateFeedDocumentResult createFeedDocumentResult = JSON.parseObject(body, CreateFeedDocumentResult.
                    class);
            String body1 = AmazonUtil.download(createFeedDocumentResult.getUrl(), "application/xml,charset=utf-8");
            JSONObject jsonObject = XmlUtils.xml2Json(body1);
            FeedUploadResultBean bean = JSON.parseObject(jsonObject.getJSONObject("AmazonEnvelope").getJSONArray("Message")
                    .getJSONObject(0).getJSONArray("ProcessingReport").getString(0), FeedUploadResultBean.class);
            if ("Complete".equals(bean.getStatusCode())) {
                int successFulCount = Integer.parseInt(bean.getProcessingSummary().get(0).getMessagesSuccessful());
                int processCount = Integer.parseInt(bean.getProcessingSummary().get(0).getMessagesProcessed());
                int errorCount = Integer.parseInt(bean.getProcessingSummary().get(0).getMessagesWithError());
                if (successFulCount == orderIds.size()) {
                    log.info(String.format("amazon修改本地订单状态开始,数量%d", orderIds.size()));
                    int count = dao.updateOrderUploadTrack(orderIds);
                    operateRecordDao.operateAddRecord(SysConstant.OPERATE_UPLOAD_TRACK, orderIds, 1L, 4);
                    log.info(String.format("amazon修改本地订单状态结束，数量%d", count));
                }
            }
            return createFeedDocumentResult.getFeedDocumentId();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 创建feeds模板
     *
     * @return
     */
    private String createFeedsDocuments(String accessToken) {
        try {
            Map parametersMap = new HashMap<>();
            parametersMap.put("contentType", "text/xml; charset=UTF-8");
            System.out.println(SHA256Utils.getSHA256(JSON.toJSONString(parametersMap)));
            log.info(JSONObject.toJSONString(parametersMap));
            String body = AmazonUtil.spAPidoPOST("https://sellingpartnerapi-fe.amazon.com/feeds/2021-06-30/documents",
                    accessToken, getAwsSTSSessionToken(), parametersMap, JSON.toJSONString(parametersMap));
            log.info(body);
            return body;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 上传模板文件
     *
     * @param integerListEntry
     * @return
     */
    private String uploadFeeds(Map.Entry<Long, List<OrderFulfillment>> integerListEntry) {
        List<String> orderIds = new ArrayList<>();
        CreateFeedDocumentResult createFeedDocumentResult;
        ShopDo shopBean = shopDao.selectById(integerListEntry.getKey());
        List<AmzSubmitFeedMessage> messageList = new ArrayList<>();
        String accessToken = null;
        try {
            accessToken = getAccessToken(shopBean);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String body1 = createFeedsDocuments(accessToken);
        JSONObject jsonObject = JSONObject.parseObject(body1);
        if (jsonObject.getJSONArray("errors") != null) {
            if (jsonObject.getJSONArray("errors").getJSONObject(0).getString("code").equals("Unauthorized")) {
                try {
                    accessToken = getAccessToken(shopBean);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        for (int i = 0; i < integerListEntry.getValue().size(); i++) {
            AmzSubmitFeedMessage message = new AmzSubmitFeedMessage();
            message.setMessageID(String.valueOf(i + 1));
            message.setOperationType("Update");
            message.setOrderFulfillment(integerListEntry.getValue().get(i));
            orderIds.add(integerListEntry.getValue().get(i).getAmazonOrderID());
            messageList.add(message);
        }
        try {
            createFeedDocumentResult =
                    JSON.parseObject(jsonObject.toString(), CreateFeedDocumentResult.class);
            String body = AmazonUtil.uploadFeedsDocumentsFile(messageList, shopBean.getAmazonSellerId(),
                    createFeedDocumentResult.getUrl());
            if (StringUtils.isBlank(createFeedDocumentResult.getFeedDocumentId())) return null;
            String feedId = createFeed(createFeedDocumentResult.getFeedDocumentId(), accessToken);
            getFeed(feedId, accessToken, getAwsSTSSessionToken(), orderIds);
            return createFeedDocumentResult.getFeedDocumentId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public SingleResult adToken(String code) {
//        try {
//          String body =  AmazonUtil.spGetAdToken("amzn1.application-oa2-client.00b038d429444f14adedf66af0fb07a4","94448a3d8859a31550fd6ffc1b7efb9eb5ce76c330014879bb2557a4337e573d"
//            ,code);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return null;
    }

    @Override
    public void getFeedTest(int i, String feedId) {
        ShopDo shopDo = shopDao.selectById(i);
        try {
            getFeed(feedId, getAccessToken(shopDo), getAwsSTSSessionToken(), new ArrayList<>());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
